package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.anno.GuiGuCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.context.UpdateUserPaidRecordStrategyContext;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.mapper.UserPaidAlbumMapper;
import com.atguigu.tingshu.user.mapper.UserPaidTrackMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Override
    public String wxLogin(String code) {
        // 校验code
        if (StringUtils.isEmpty(code)) {
            throw new GuiguException(ResultCodeEnum.ARGUMENT_VALID_ERROR);
        }
        try {
            // 调用微信接口校验凭证的合法性
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            //校验通过 获取到openid
            String openid = sessionInfo.getOpenid();
            UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
            if (userInfo == null) {
                userInfo = new UserInfo(); //创建对象
                userInfo.setWxOpenId(openid);
                userInfo.setNickname("听友" + System.currentTimeMillis());
                userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
                userInfo.setStatus("1");
                userInfo.setIsVip(0);
                userInfoMapper.insert(userInfo);
                //初始化用户信息
                kafkaService.sendMsg(KafkaConstant.QUEUE_USER_REGISTER, String.valueOf(userInfo.getId()));
            }
            //创建token登录令牌
            String token = UUID.randomUUID().toString().replaceAll("-", "");
            //创建redis中的key
            String key = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
            //通过opsForValue()方法将userInfo对象转换为json字符串保存到redis中
            stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(userInfo), RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
            //返回token
            return token;
        } catch (WxErrorException e) {
            e.printStackTrace();
            throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);
        }

    }

    @Override
    public UserInfoVo getUserInfo(Long userId) {
        //根据userid查询数据库返回userinfo
        UserInfo userInfo = this.getById(userId);
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        return userInfoVo;
    }

    @Override
    public void updateUser(UserInfoVo userInfoVo) {
        Long userId = AuthContextHolder.getUserId();
        UserInfo userInfo = this.getById(userId);
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
        userInfo.setId(userId);
        userInfoMapper.updateById(userInfo);
    }

    @GuiGuCache(cacheKey = RedisConstant.USER_INFO_PREFIX + "#{#params[0]}", enableLock = true, lockName = RedisConstant.USER_LOCK_PREFIX + "#{#params[0]}")
    @Override
    public UserInfo getUserInfoById(Long userId) {
        return this.getById(userId);
    }

    @Override
    public Map<Long, Long> userIsPaidTrack(Long albumId, List<Long> trackIdList) {
        Map<Long, Long> map = new HashMap<>();
        //调用mapper方法查询用户是否购买过该专辑
        Long userId = AuthContextHolder.getUserId();
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>()
                .eq(UserPaidAlbum::getUserId, userId)
                .eq(UserPaidAlbum::getAlbumId, albumId));
        if(userPaidAlbum!= null){
            trackIdList.stream().forEach(trackId->map.put(trackId,1L));
        }else{
            List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
                    .eq(UserPaidTrack::getUserId, userId)
                    .in(UserPaidTrack::getTrackId, trackIdList));
            List<Long> collect = userPaidTracks.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
//            trackIdList.forEach(trackId->{
//                long IsPaidResult = collect.contains(trackId) ? 1L : 0L;
//                map.put(trackId,IsPaidResult);
//            });
            for (Long trackId : trackIdList) {
                long IsPaidResult = collect.contains(trackId) ? 1L : 0L;
                map.put(trackId,IsPaidResult);
            }

        }
        return map;
    }

    @Override
    public Boolean isPaidAlbum(Long albumId, Long userId) {

        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId)
                .eq(UserPaidAlbum::getUserId, userId));

        return userPaidAlbum != null;
    }

    @Override
    public List<Long> findUserTrackPaidList(Long albumId) {
        Long userId = AuthContextHolder.getUserId();

        //根据用户id和专辑id查询用户购买过的声音
        List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId)
                .eq(UserPaidTrack::getAlbumId, albumId));

        return userPaidTracks.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());

    }

    @Override
    public void updateUserPaidRecord(UserPaidRecordVo userPaidRecordVo) {
        UpdateUserPaidRecordStrategyContext.getStrategy(userPaidRecordVo.getItemType()).updateUserPaid(userPaidRecordVo);
    }

    @Override
    public void updateVipExpireStatus() {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getIsVip, 1);
        queryWrapper.lt(UserInfo::getVipExpireTime, new DateTime());

        List<UserInfo> userInfos = userInfoMapper.selectList(queryWrapper);
        userInfos.forEach(userInfo -> {
            userInfo.setIsVip(0);
            userInfoMapper.updateById(userInfo);
        });

    }
}
